#!/usr/bin/perl
#
# Script to replace SUNDIALS Copyright.
#

use strict;

use File::Basename;
use File::Find;
use File::Path;
use File::Compare;
use Cwd;
use Text::Wrap;
use File::Copy;
use File::stat;

my $pwd = cwd;

my $debug = 2;

#
# File pattern to look for
#
my $filePattern;
my $excludePattern;
my @allfiles = ();

sub selectFile {
    if ( $File::Find::dir =~ m!$excludePattern! ) {
        $File::Find::prune = 1;
    }
    elsif ( ! -l && -f && m/$filePattern/ ) {
        push @allfiles, $File::Find::name;
        $allfiles[$#allfiles] =~ s|^\./||;
    }
    else {
    }
}

sub replaceInFiles {
    $filePattern=$_[0];
    $excludePattern=$_[1];
    my $replacePattern=$_[2];
    my $newPattern=$_[3];

    @allfiles = ();
    find( \&selectFile, "." );
    print "files=@allfiles" if ($debug > 2);
    foreach my $file (@allfiles) {

        print "Working on $file\n";
        my $filebasename = basename $file;

        my $tempFile = $filebasename . ".replace.tmp";

        open FILE, "< $file" || die "Cannot open file $file";
        my $str = do { local $/; <FILE> };

        open TEMPFILE, "> $tempFile" || die "Cannot open temporary work file $tempFile";

        $str =~ s/$replacePattern/$newPattern/gs;

        print TEMPFILE $str;

        close FILE || die "Cannot close file $file";
        close TEMPFILE || die "Cannot close file $tempFile";

        printf "Replacing original file\n" if ($debug > 2);

        # Only replace existing file if a replacement was done.
        if (compare($file,$tempFile) == 0) {
            # remove temporary file
            unlink($tempFile);
        } else {
            # get the permissions of the original file
            my $info = stat($file);
            my $ret_mode = $info->mode;

            # replace the original file
            unlink($file);
            rename( $tempFile, $file);

            # set the permissions for the new file
            chmod $ret_mode, $file;
        }
    }
}


# Flush I/O on write to avoid buffering
$|=1;

my $end_of_line = $/;

my $endyear = '2025';

my $newCopyright = <<"END";
 # SUNDIALS Copyright Start
 # Copyright (c) 2002-$endyear, Lawrence Livermore National Security
 # and Southern Methodist University.
 # All rights reserved.
 #
 # See the top-level LICENSE and NOTICE files for details.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 # SUNDIALS Copyright End
END

# files to exclude
my $fileExcludePattern=q!/(.git)$!;

##############################################################################
# Replace copyright year in cases without copyright "Start" and "End" markers
# e.g., LICENSE file, doc file text, and python strings
##############################################################################

my $docFilePattern    = q!(LICENSE|\.tex|\.rst|\.py)$!;
my $docReplacePattern = 'Copyright \(c\) (.*?),';
my $docNewCopyright   = "Copyright (c) 2002-$endyear,";

replaceInFiles($docFilePattern,$fileExcludePattern,$docReplacePattern,$docNewCopyright);

#############################################################################
# Replace in C/C++/CUDA source files
#############################################################################

my $cFilePattern    = q!(\.[chI]|\.cpp|\.hpp|\.cu|\.cuh|\.in|\.def)$!;
my $cReplacePattern = ' \* (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*)Copyright End\n';
my $cNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$cNewCopyright =~ s/#/\*/g;

replaceInFiles($cFilePattern,$fileExcludePattern,$cReplacePattern,$cNewCopyright);

#############################################################################
# Replace in Fortran files
#############################################################################

my $fFilePattern    = q!(\.f|\.f90|\.in)$!;
my $fReplacePattern = '! (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*)Copyright End\n';
my $fNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$fNewCopyright =~ s/ #/!/g;

replaceInFiles($fFilePattern,$fileExcludePattern,$fReplacePattern,$fNewCopyright);

my $fFilePattern    = q!(\.f)$!;
my $fReplacePattern ='(C|c)     (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*)Copyright End\n';
my $fNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$fNewCopyright =~ s/ # (\w)/C     $1/g;
$fNewCopyright =~ s/ #/C/g;

replaceInFiles($fFilePattern,$fileExcludePattern,$fReplacePattern,$fNewCopyright);

#############################################################################
# Replace in CMake/Make files
#############################################################################

my $cmakeFilePattern    = q!(CMakeLists.txt|\.cmake|\.cmake.template|Makefile|\.in)$!;
my $cmakeReplacePattern = '# (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*)Copyright End\n';
my $cmakeNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$cmakeNewCopyright =~ s/ #/#/g;

replaceInFiles($cmakeFilePattern,$fileExcludePattern,$cmakeReplacePattern,$cmakeNewCopyright);

#############################################################################
# Replace in Python/Shell/YAML files
#############################################################################

my $shFilePattern    = q!(\.py|\.sh|\.yml|testRunner)$!;
my $shReplacePattern = '# (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*)Copyright End\n';
my $shNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$shNewCopyright =~ s/ #/#/g;

replaceInFiles($shFilePattern,$fileExcludePattern,$shReplacePattern,$shNewCopyright);

#############################################################################
# Replace in Swig files
#############################################################################

my $sFilePattern    = q!(\.i)$!;
my $sReplacePattern = '// (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*?)Copyright End\n';
my $sNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$sNewCopyright =~ s| #|//|g;

replaceInFiles($sFilePattern,$fileExcludePattern,$sReplacePattern,$sNewCopyright);

my $sFilePattern    = q!(\.i)$!;
my $sReplacePattern = ' \* (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*?)Copyright End\n';
my $sNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$sNewCopyright =~ s/ #/ */g;

replaceInFiles($sFilePattern,$fileExcludePattern,$sReplacePattern,$sNewCopyright);

my $sFilePattern    = q!(\.i)$!;
my $sReplacePattern = '! (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*?)Copyright End\n';
my $sNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$sNewCopyright =~ s/ #/!/g;

replaceInFiles($sFilePattern,$fileExcludePattern,$sReplacePattern,$sNewCopyright);

##############################################################################
## Replace in rst files
##############################################################################

my $rstFilePattern    = q!(\.rst|\.rest)$!;
my $rstReplacePattern = '   (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*)Copyright End\n';
my $rstNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$rstNewCopyright =~ s/ # /   /g;
$rstNewCopyright =~ s/ #//g;

replaceInFiles($rstFilePattern,$fileExcludePattern,$rstReplacePattern,$rstNewCopyright);

#############################################################################
# Replace in LateX/BibTeX files
#############################################################################

my $texFilePattern    = q!(\.tex|\.bib)$!;
my $texReplacePattern = '% (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*)Copyright End\n';
my $texNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$texNewCopyright =~ s/ #/\%/g;

replaceInFiles($texFilePattern,$fileExcludePattern,$texReplacePattern,$texNewCopyright);

#############################################################################
# Replace in Matlab files
#############################################################################

my $matlabFilePattern    = q!(\.[m]|\.in)$!;
my $matlabReplacePattern = '% (LLNS|LLNS/SMU|SUNDIALS) Copyright Start(.*)Copyright End\n';
my $matlabNewCopyright   = $newCopyright;

# replace comment character(s) in new copyright
$matlabNewCopyright =~ s/ #/\%/g;

replaceInFiles($matlabFilePattern,$fileExcludePattern,$matlabReplacePattern,$matlabNewCopyright);
